package gupdate

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"time"
)

// 运行程序，检查更新
var version string
var path string
var reload bool

var exePath string
var exeName string
var tempFilePath string

func Run(Version, url string, Reload bool) {
	version = Version
	path = url
	reload = Reload
	exePath, _ = os.Executable()
	exeName = filepath.Base(exePath)
	fmt.Println("当前版本:", version)
	fmt.Println("程序路径:", exePath)
	fmt.Println("程序名称:", exeName)
	go checkUpdate()
}

// 循环检测更新
func checkUpdate() {
	for {
		V, err := checkForUpdate()
		if err == nil && V.Version != "" {
			fmt.Printf("New version available: %s\n", V.Version)
			err = downloadNewVersion(V.Name)
			if err != nil {
				fmt.Println("Error downloading new version:", err)
			} else {
				err = replaceCurrentVersion(V)
				if err != nil {
					fmt.Println("Error replacing current version:", err)
				}
			}
		}
		time.Sleep(10 * time.Second)
	}
}

//检查版本号

func checkForUpdate() (reVersion, error) {
	// 假设服务器返回最新的版本号
	vdata := reVersion{}
	resp, err := http.Get(path + "/version.json")
	if err != nil {
		return vdata, err
	}
	defer resp.Body.Close()

	vjson, err := io.ReadAll(resp.Body)
	if err != nil {
		return vdata, err
	}
	json.Unmarshal(vjson, &vdata)
	if vdata.Version == version {
		vdata.Version = ""
	}
	//如果版本小于当前程序版本，则不更新
	if vdata.Version != "" && vdata.Version < version {
		vdata.Version = ""
	}
	return vdata, nil
}
func downloadNewVersion(name string) error {
	url := fmt.Sprintf(path+"/%s", name)
	//获取当前运行程序的名称
	resp, err := http.Get(url)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	// 将新版本保存到临时文件
	//当前时间戳
	tempFile, err := os.CreateTemp("", "app-"+name+"-"+".bin")
	if err != nil {
		return err
	}
	defer tempFile.Close()
	_, err = io.Copy(tempFile, resp.Body)
	if err != nil {
		return err
	}

	// 记录临时文件路径
	tempFilePath = tempFile.Name()
	// 这里可以将 tempFilePath 传递给替换和重启逻辑
	return nil
}
func replaceCurrentVersion(V reVersion) error {
	// 使用系统命令替换当前可执行文件
	//把当前正在使用的文件改名
	os.Rename(exePath, exePath+".bak")
	//复制到当前文件
	err := CopyFile(tempFilePath, exePath)
	if err != nil {
		return err
	}
	os.Remove(tempFilePath)
	tempFilePath = ""
	os.Remove(exePath + ".bak")
	fmt.Println("Update completed successfully.")
	version = V.Version
	if reload {
		// 重启应用
		cmd := exec.Command(exePath)
		cmd.Stdin = os.Stdin
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr

		if err = cmd.Start(); err != nil {
			return err
		}
		// 退出当前进程
		os.Exit(0)
	}

	return nil
}

// CopyFile 复制文件从 src 到 dst
func CopyFile(src, dst string) error {
	// 打开源文件
	in, err := os.Open(src)
	if err != nil {
		return err
	}
	defer in.Close()

	// 创建目标文件
	out, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer out.Close()

	// 复制文件内容
	_, err = io.Copy(out, in)
	if err != nil {
		return err
	}

	// 同步文件内容到磁盘
	err = out.Sync()
	if err != nil {
		return err
	}

	return nil
}
